package edu.cmu.vlis.distributed.relationalalgebra.visitor;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import edu.cmu.vlis.distributed.relationalalgebra.*;

public class AlegbraTreePrintVisitor implements AVisitor<AlgebraNode> {
		
	//us ps to print result
	private PrintStream ps = System.out;
	
	public AlegbraTreePrintVisitor(PrintStream ps) {
		this.ps = ps;
	}

	@Override
	public AlgebraNode visitNode(Join node) {
		// Find level to tab correctly
		String tabs = "";
		AlgebraNode fature = node.getFather();
		while (fature != null) {
			tabs += "\t";
			fature = fature.getFather();
		}
		
		ps.println(tabs + node.toString());
		
		AlgebraNode newLeft = node.getLeft().accept(this);
		if (newLeft == null)
			return null;
		node.setLeft(newLeft);

		AlgebraNode newRight = node.getRight().accept(this);
		if (newRight == null)
			return null;
		node.setRight(newRight);
		return node;
	}

	@Override
	public AlgebraNode visitNode(Selection node) {
		// Find level to tab correctly
		String tabs = "";
		AlgebraNode fature = node.getFather();
		while (fature != null) {
			tabs += "\t";
			fature = fature.getFather();
		}
		
		ps.println(tabs + node.toString());
		
		AlgebraNode newChild = node.getChild().accept(this);

		if (newChild == null) {
			return null;
		}

		node.setChild(newChild);
		return node;
	}

	@Override
	public AlgebraNode visitNode(Relation node) {
		// Find level to tab correctly
		String tabs = "";
		AlgebraNode fature = node.getFather();
		while (fature != null) {
			tabs += "\t";
			fature = fature.getFather();
		}
		
		ps.println(tabs + node.toString());
		return node;
	}

	@Override
	public AlgebraNode visitNode(Union node) {
		// Find level to tab correctly
		String tabs = "";
		AlgebraNode fature = node.getFather();
		while (fature != null) {
			tabs += "\t";
			fature = fature.getFather();
		}
		
		ps.println(tabs + node.toString());
		
		List<AlgebraNode> newChildren = new ArrayList<AlgebraNode>();
		for (AlgebraNode child : node.getChildren()) {
			AlgebraNode newChild = child.accept(this);
			if (newChild != null) {
				newChildren.add(newChild);
			}
		}
		node.setChildren(newChildren);
		if (newChildren.size() == 1) {
			return newChildren.get(0);
		}
		if (newChildren.size() == 0) {
			return null;
		}
		
		return node;
	}

	@Override
	public AlgebraNode visitNode(Fragment node) {
		// Find level to tab correctly
		String tabs = "";
		AlgebraNode fature = node.getFather();
		while (fature != null) {
			tabs += "\t";
			fature = fature.getFather();
		}
		
		ps.println(tabs + node.toString());
		return node;
	}

	@Override
	public AlgebraNode visitNode(Projection node) {
		// Find level to tab correctly
		String tabs = "";
		AlgebraNode fature = node.getFather();
		while (fature != null) {
			tabs += "\t";
			fature = fature.getFather();
		}
		
		ps.println(tabs + node.toString());
		AlgebraNode newChild = node.getChild().accept(this);

		if (newChild == null) {
			return null;
		}

		node.setChild(newChild);
		return node;
	}
	
	
}
